package com.myorg.service;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.apache.hadoop.fs.FSDataOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.myorg.domain.Email;
import com.myorg.util.ConstantsToBeExternalized;
import com.myorg.util.HdfsHelper;
import com.myorg.util.Utility;

//TODO: Auto-wiring is not there yet.
public class FakeEmailGenerationService {
	final static private Logger logger = LoggerFactory.getLogger(FakeEmailGenerationService.class);
	private static List<String> words = new ArrayList<String>();

	public FakeEmailGenerationService() {
		if (words.isEmpty()) {
			loadWords();
		}
	}

	private void loadWords() {
		logger.info("Loading words from: " + ConstantsToBeExternalized.DICTIONARY_URL_LOCAL);
		try {
			URL url = new URL(ConstantsToBeExternalized.DICTIONARY_URL_LOCAL);
			BufferedReader in = null;
			try {
				in = new BufferedReader(new InputStreamReader(url.openStream()));
			} catch (FileNotFoundException e) {
				url = new URL(ConstantsToBeExternalized.DICTIONARY_URL_REMOTE);
				in = new BufferedReader(new InputStreamReader(url.openStream()));
			}
			String line;
			while ((line = in.readLine()) != null) {
				words.add(line);
			}
			in.close();
		} catch (MalformedURLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	private String retrieveRandomWord() {
		return words.get(new Random().nextInt(words.size()));
	}

	private String generateRandomParagragh() {
		StringBuilder sb = new StringBuilder();
		int size = 12 + new Random().nextInt(100);
		for (int i = 0; i < size; i++) {
			if (sb.length() > 0) {
				sb.append(" ");
			}
			sb.append(retrieveRandomWord());
		}
		return sb.toString();
	}

	private String generateRandomEmailContent() {
		StringBuilder sb = new StringBuilder();
		int size = 1 + new Random().nextInt(5);
		for (int i = 0; i < size; i++) {
			sb.append(generateRandomParagragh()).append("\n\n");
		}
		return sb.toString();
	}

	private Email generateOneEmail() {
		Email email = new Email();
		email.setId(Utility.generateUUID());
		email.setContent(generateRandomEmailContent());
		return email;
	}

	public void generateFakeEmails(final long maxSize, final boolean compress, String targetPathInHdfs) {
		logger.info("Generating fake email file: " + targetPathInHdfs + ", " + maxSize + ", " + compress);
		HdfsHelper helper = new HdfsHelper();
		helper.saveToHDFS(targetPathInHdfs, new HdfsHelper.IHDFSFileSaver() {
			@Override
			public void save(final FSDataOutputStream targetOutputStream) {
				long pos = 0L;
				while (pos < maxSize) {
					Email e = generateOneEmail();
					e.persist(targetOutputStream, compress);
					pos += e.getSize();
				}
			}
		});
		logger.info("Generating done!");
	}
}
